////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __WN_MEMORY_ALLOCATION_H__
#define __WN_MEMORY_ALLOCATION_H__

#include "WNCore/inc/WNPlatform.h"
#include "WNCore/inc/WNTypes.h"

#ifdef _WN_WINDOWS
    #include <malloc.h>

    #define WN_STACK_ALLOC(_size) _alloca(_size)
#elif defined _WN_LINUX
    #include <alloca.h>

    #define WN_STACK_ALLOC(_size) alloca(_size)
#endif

#define WN_NEW(_object) new _object
#define WN_ARRAY_NEW(_object, _count) new _object[_count]
#define WN_PLACEMENT_NEW(_object, _location) new(_location) _object

#ifdef _WN_DEBUG
    #define WN_DELETE(_object) delete _object; _object = WN_NULL
    #define WN_ARRAY_DELETE(_object) delete[] _object; _object = WN_NULL
#else
    #define WN_DELETE(_object) delete _object
    #define WN_ARRAY_DELETE(_object) delete[] _object
#endif

typedef WN_VOID* (*WN_MALLOC_FUNCTION_T)(WN_SIZE_T);
typedef WN_VOID* (*WN_CALLOC_FUNCTION_T)(WN_SIZE_T, WN_SIZE_T);
typedef WN_VOID* (*WN_REALLOC_FUNCTION_T)(WN_VOID*, WN_SIZE_T);
typedef WN_VOID (*WN_FREE_FUNCTION_T)(WN_VOID*);

typedef WN_VOID* (*WN_ALIGNED_MALLOC_FUNCTION_T)(WN_SIZE_T, WN_SIZE_T);
typedef WN_VOID* (*WN_ALIGNED_CALLOC_FUNCTION_T)(WN_SIZE_T, WN_SIZE_T, WN_SIZE_T);
typedef WN_VOID* (*WN_ALIGNED_REALLOC_FUNCTION_T)(WN_VOID*, WN_SIZE_T, WN_SIZE_T);
typedef WN_VOID (*WN_ALIGNED_FREE_FUNCTION_T)(WN_VOID*);

namespace WNMemory {
    WN_INLINE WN_VOID* WNMalloc(WN_SIZE_T _size);
    WN_INLINE WN_VOID* WNCalloc(WN_SIZE_T _count, WN_SIZE_T _size);
    WN_INLINE WN_VOID* WNRealloc(WN_VOID* _memory, WN_SIZE_T _size);
    WN_INLINE WN_VOID WNFree(WN_VOID* _memory);

    template <typename Type> Type* WNMallocT(WN_SIZE_T _amount = 1);
    template <typename Type> Type* WNCallocT(WN_SIZE_T _count, WN_SIZE_T _amount);
    template <typename Type> Type* WNReallocT(Type* _memory, WN_SIZE_T _amount);
    template <typename Type> WN_VOID WNFreeT(Type* _memory);

    WN_INLINE WN_VOID* WNAlignedMalloc(WN_SIZE_T _size, WN_SIZE_T _alignment);
    WN_INLINE WN_VOID* WNAlignedCalloc(WN_SIZE_T _count, WN_SIZE_T _size, WN_SIZE_T _alignment);
    WN_INLINE WN_VOID* WNAlignedRealloc(WN_VOID* _memory, WN_SIZE_T _size, WN_SIZE_T _alignment);
    WN_INLINE WN_VOID WNAlignedFree(WN_VOID* _memory);

    template <typename Type> Type* WNAlignedMallocT(WN_SIZE_T _amount, WN_SIZE_T _alignment);
    template <typename Type> Type* WNAlignedCallocT(WN_SIZE_T _count, WN_SIZE_T _amount, WN_SIZE_T _alignment);
    template <typename Type> Type* WNAlignedReallocT(Type* _memory, WN_SIZE_T _amount, WN_SIZE_T _alignment);
    template <typename Type> WN_VOID WNAlignedFreeT(Type* _memory);
}

#include "WNMemory/inc/WNAllocation.inl"

#endif // __WN_MEMORY_ALLOCATION_H__